package Day_0207.Redis;

/**
 * @author zxc
 * @date 2023/02/07 23:22
 **/
public class Redis_Common_Problems {
    public static void main(String[] args) {
        /**
         * 缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等问题
         * ===》
         * 一、缓存雪崩
         * 1.概念 ：
         * （1）由于原有缓存失效，新缓存未到期间 (例如：我们设置缓存时采用了相同的过期时间，在同一时刻出现大面积的缓存过期)，
         * （2）所有原本应该访问缓存的请求都去查询数据库了，而对数据库CPU和内存造成巨大压力，严重的会造成数据库宕机。
         *
         * 2.解决办法：
         * （1）考虑用加锁（ 最多的解决方案）或者队列的方式，来保证不会有大量的线程对数据库一次性进行读写，
         *  ===> 从而避免失效时大量的并发请求落到底层存储系统上。
         * （2）使得缓存失效时间分散开。
         *
         * 二、缓存穿透
         * 1.概念 ：
         * （1）缓存穿透是指用户查询数据，在数据库没有，自然在缓存中也不会有。
         * （2）这样就导致用户查询的时候，在缓存中找不到，每次都要去数据库再查询一遍，然后返回空（相当于进行了两次无用的查询）。
         * （3）这样请求就绕过缓存直接查数据库，这也是经常提的缓存命中率问题。
         *
         * 2.解决办法;
         * （1）最常见的则是采用布隆过滤器，
         *  将所有可能存在的数据哈希到一个足够大的bitmap中，一个一定不存在的数据会被这个bitmap拦截掉，从而避免了对底层存储系统的查询压力。
         * （2）如果一个查询返回的数据为空（不管是数据不存在，还是系统故障），我们仍然把这个空结果进行缓存，但它的过期时间会很短，最长不超过五分钟。
         *  通过这个直接设置的默认值存放到缓存，这样第二次到缓冲中获取就有值了，而不会继续访问数据库。
         *
         * 3.5TB的硬盘上放满了数据，请写一个算法将这些数据进行排重。如果这些数据是一些32bit大小的数据该如何解决？如果是64bit的呢？
         * 对于空间的利用到达了一种极致，那就是Bitmap和布隆过滤器(Bloom Filter)。
         * （1）Bitmap： 典型的就是哈希表
         *  缺点是，Bitmap对于每个元素只能记录1bit信息，如果还想完成额外的功能，恐怕只能靠牺牲更多的空间、时间来完成了。
         *
         * （2）布隆过滤器（推荐）：就是引入了k(k>1)k(k>1)个相互独立的哈希函数，保证在给定的空间、误判率下，完成元素判重的过程。
         *  它的优点是空间效率和查询时间都远远超过一般的算法，缺点是有一定的误识别率和删除困难。
         *
         *  4.Bloom-Filter算法的核心思想就是利用多个不同的Hash函数来解决“冲突”。
         *  （1）Hash存在一个冲突（碰撞）的问题，用同一个Hash得到的两个URL的值有可能相同。
         *  （2）为了减少冲突，我们可以多引入几个Hash，如果通过其中的一个Hash值我们得出某元素不在集合中，那么该元素肯定不在集合中。
         *  （3）只有在所有的Hash函数告诉我们该元素在集合中时，才能确定该元素存在于集合中。这便是Bloom-Filter的基本思想。
         *
         *  5.布隆过滤器的适用场景 ：
         *  Bloom-Filter（布隆过滤器），一般用于在大数据量的集合中判定某元素是否存在。
         *
         * 三、缓存预热
         * 1.概念 ：
         * （1）缓存预热就是系统上线后，将相关的缓存数据直接加载到缓存系统。
         * （2）这样就可以避免在用户请求的时候，先查询数据库，然后再将数据缓存的问题！用户直接查询事先被预热的缓存数据！
         *
         * 2.解决思路：
         * 1、直接写个缓存刷新页面，上线时手工操作下；
         * 2、数据量不大，可以在项目启动的时候自动进行加载；
         * 3、定时刷新缓存；
         *
         * 四、缓存更新
         * 除了缓存服务器自带的缓存失效策略之外（Redis默认的有6中策略可供选择），
         * 我们还可以根据具体的业务需求进行自定义的缓存淘汰，常见的策略有两种：
         * （1）定时去清理过期的缓存；
         * （2）当有用户请求过来时，再判断这个请求所用到的缓存是否过期，过期的话就去底层系统得到新数据并更新缓存。
         * ===》
         * 两者各有优劣，第一种的缺点是维护大量缓存的key是比较麻烦的，
         * 第二种的缺点就是每次用户请求过来都要判断缓存失效，逻辑相对比较复杂！
         *
         * 五、缓存降级
         * 1.概念 ：
         * （1）当访问量剧增、服务出现问题（如响应时间慢或不响应）或非核心服务影响到核心流程的性能时，仍然需要保证服务还是可用的，即使是有损服务。
         * （2）系统可以根据一些关键数据进行自动降级，也可以配置开关实现人工降级。
         *
         * 2.缓存降级目的
         * 降级的最终目的是保证核心服务可用，即使是有损的。
         * 而且有些服务是无法降级的（如加入购物车、结算）。 以参考日志级别设置预案：
         * （1）一般：比如有些服务偶尔因为网络抖动或者服务正在上线而超时，可以自动降级；
         * （2）警告：有些服务在一段时间内成功率有波动（如在95~100%之间），可以自动降级或人工降级，并发送告警；
         * （3）错误：比如可用率低于90%，或者数据库连接池被打爆了，或者访问量突然猛增到系统能承受的最大阀值，此时可以根据情况自动降级或者人工降级；
         * （4）严重错误：比如因为特殊原因数据错误了，此时需要紧急人工降级。
         *
         * 3.服务降级的目的，是为了防止Redis服务故障，导致数据库跟着一起发生雪崩问题。
         * ===》
         * 因此，对于不重要的缓存数据，可以采取服务降级策略，
         * 例如一个比较常见的做法就是，Redis出现问题，不去数据库查询，而是直接返回默认值给用户。
         *
         */
    }
}
